<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<style type="text/css">
    body {
        margin: 0;
        padding: 0;
    }

    .main {
        width: 800px;
        height: 400px;
        margin: 50px auto;
    }

    .btn {
        width: 100px;
        height: 40px;
    }

    .map {
        position: relative;
        width: 800px;
        height: 400px;
        background: #ccc;
    }
</style>

<body>
    <div class="main">
        <button class="btn1" id="start">开始游戏</button>
        <button class="btn2" id="pause">暂停游戏</button>
        <button class="btn3" id="stop1">停止游戏</button>
        <button class="btn4" id="score">得分:0</button>
        <div class="map" id="map"></div>
    </div>
</body>

</html>
<script>
    //通过面向对象，基于class类的继承来写的
    class Tools {
        $ = id => document.getElementById(id);
        _c = tagName => document.createElement(tagName);
    }
    
    class food extends Tools {
        constructor() {
            super()
            this.width = 15;
            this.height = 15;
            this.map = this.$('map');
        }
        //在区域内随机生成一个食物
        creatFood() {
            let food = this._c('div');
            food.style.width = this.width + 'px';
            food.style.height = this.height + 'px';
            console.log(this.width);
            food.style.backgroundColor = 'yellow';
            food.style.border = '1px solid #000';

            let left = (Math.floor(Math.random() * parseInt(this.map.offsetWidth / this.width))) * this.width;
            let right = (Math.floor(Math.random() * parseInt(this.map.offsetHeight / this.height))) * this.height;
            this.foodX = left;
            this.foodY = right;

            food.style.position = 'absolute';
            food.style.left = left + 'px';
            food.style.top = right + 'px';
            this.food = food;
            this.map.appendChild(this.food);
        }
        //让生成的食物消失
        removeFood() {
            this.map.removeChild(this.food);
            this.food = null;
        }

    }

    class snake extends Tools { 
        constructor(foodContext) {
            super()
            this.body = [
                { x: 2, y: 0 },
                { x: 1, y: 0 },
                { x: 0, y: 0 }
            ]
            this.height = 15;
            this.width = 15;
            this.map = this.$('map');
            this.direction = 'right';
            this.keyEvent();
            if (foodContext instanceof food) {
                this.f = foodContext;

            } else {
                alert('传入实例错误')
            }
            this.count = 0;
        }

        //实现上下左右键控制蛇运动的方向
        keyEvent() {
            document.onkeydown = (e) => {
                //通过键盘码来判断
                switch (e.keyCode) {
                    case 37:
                        this.direction = 'left'
                        break;
                    case 38:
                        this.direction = 'up'
                        break;
                    case 39:
                        this.direction = 'right'
                        break;
                    case 40:
                        this.direction = 'down'
                }
            }
        }
        //将初始的蛇绘制在map中，实现游戏初始状态
        display() {
           
            this.body.forEach(item => {
                if (item.oldNode) {
                    this.map.removeChild(item.oldNode);
                }
                let div = this._c('div');
                div.style.backgroundColor = 'hotpink';
                div.style.border = '1px solid #000';
                div.style.width = this.width + 'px';
                div.style.height = this.height + 'px';
                div.style.position = 'absolute';
                div.style.left = item.x * this.width + 'px';
                div.style.top = item.y * this.height + 'px';
                item.oldNode = div;
                this.map.appendChild(div);
                this.btn4 = this.$('score');
            })
        }
        //不断设置蛇尾小方块的left和top值让蛇实现跑起来的效果
        run() {

            let final = this.body.pop();
            let first = { ...this.body[0] };
            //解构，从first里拿出x和y的值
            let { x } = first;
            let { y } = first;
            switch (this.direction) {
                case 'left':
                    x -= 1
                    break;
                case 'up':
                    y -= 1
                    break;
                case 'right':
                    x += 1
                    break;
                case 'down':
                    y += 1
            }
           

            final.x = x;
            final.y = y;

            let snakeHeadX = x * this.width;
            let snakeHeadY = y * this.height;

            if (snakeHeadX === this.f.foodX && snakeHeadY === this.f.foodY) {
                this.body.push({ x, y })
                this.count++;
                this.f.removeFood();
                this.f.creatFood();
            }
            this.btn4.innerHTML = '得分:' + this.count;
            this.body.unshift(final);
            this.display();
            if (snakeHeadX < 0 || snakeHeadX > this.map.offsetWidth - this.width || (snakeHeadY < 0 && this.direction == 'up') || snakeHeadY > this.map.offsetHeight - this.height) {
                alert('游戏结束');
                b.stopGame()
            }
        }

    }
     //三个按钮的功能实现
    class btnControlor extends Tools {
        constructor(snakeContext, foodContext) {
            super()
            this.btn1 = this.$('start');
            this.btn2 = this.$('pause');
            this.btn3 = this.$('stop1');
            if (snakeContext instanceof snake && foodContext instanceof food) {
                this.s = snakeContext;
                this.f = foodContext;

                this.btnEvent()
            } else {
                alert('传入实例错误')
            }

        }
        //给三个按钮注册点击事件
        btnEvent = () => {
            this.btn1.onclick = this.startGame;
            this.btn2.onclick = this.pauseGame;
            this.btn3.onclick = this.stopGame;
        }
        //开始按钮的功能实现
        startGame = () => {
            this.btn1.disabled = true;
            this.btn2.disabled = false;
            if (this.timer) {
                clearInterval(this.timer)
            }
            this.f.creatFood()
            this.timer = setInterval(() => {
                this.s.run();

            }, 200)
        }
        //暂停按钮的功能实现
        pauseGame = () => {
            this.btn2.disabled = true;
            this.btn1.disabled = false;
            clearInterval(this.timer)
        }
        //停止按钮的功能实现
        stopGame = () => {
            this.btn1.disabled = false;
           
            this.s.map.innerHTML = '';
            this.s.body = [
                { x: 2, y: 0 },
                { x: 1, y: 0 },
                { x: 0, y: 0 }
            ]
            clearInterval(this.timer)
            this.s.display();
            this.s.direction = 'right';
            this.s.count = 0;
            this.s.btn4.innerHTML = '得分:' + this.s.count;
        }
    }


    let t = new Tools();
    let f = new food()
    
    let s = new snake(f);
    //调用绘制蛇的方法，实现游戏初始状态
    s.display();
    
    let b = new btnControlor(s, f)


</script>